// Copyright  2012 Petr TALLA. [petr.talla@gmail.com]
// This file is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License
// as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// This file is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY;  without even the implied warranty
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU Lesser General Public License for more details.
// [http://www.gnu.org/copyleft/lesser.html]
//=============================================================================

package tc.crase.save;

import java.awt.Color;
import java.awt.geom.Point2D;

import org.codehaus.jackson.JsonNode;
import org.codehaus.jackson.node.ArrayNode;
import org.codehaus.jackson.node.ObjectNode;
import org.codehaus.jackson.node.TextNode;

import tc.crase.meta.Attrdef;
import tc.crase.meta.Descr;
import tc.crase.meta.DescrItemPath;
import tc.crase.meta.DescrItemValue;
import tc.crase.meta.LinkEstimate;
import tc.common.symbology.SfeatArea;
import tc.common.symbology.SfeatLine;
import tc.common.symbology.SfeatSymbol;
import tc.common.symbology.Style;
import tc.common.symbology.SymbolItemIregular;
import tc.crase.meta.Type;
import tc.common.symbology.Symbol;
import tc.crase.sys.XdbEx;
import tc.crase.sys.XdbRoot;
import tc.crase.sys.XobjectEx;
import tc.crase.db.Xattr;
import tc.crase.db.XattrGRP;
import tc.crase.db.XattrGXY;
import tc.crase.db.XattrSTR;
import tc.crase.db.XattrTPE;
import tc.crase.db.Xobject;

public class XdbLoad extends XdbLoadDb {
	public XdbLoad(XdbEx xdb) {
		super(xdb);
	}
	
	XdbEx xdbEx() {
		return (XdbEx)xdb;
	}
	
	@Override public void loadData(boolean metaOnly) {
		xdbEx().metadata.estimates.clear();
		xdbEx().metadata.types.clear();
		xdbEx().metadata.legend.symbols.clear();
		xdbEx().metadata.legend.styles.clear();
		
		if (metaOnly == false) {
			loadObjects();
		}
		loadDocs();
		loadEstimates();
		loadTypes();
		loadSymbols();
		loadStyles();
	}
	
	private void loadDocs() {
		ArrayNode jsonArrayDocs = (ArrayNode)jsonRoot.get("docs");
		
		if (jsonArrayDocs == null) return; 
		
		//XdbEx dbex = XdbRoot.xdbsys.current;
		XdbEx dbex = (XdbEx)xdb;
		
		for ( int i = 0; i < jsonArrayDocs.size(); i++ )
		{	ObjectNode node = (ObjectNode)jsonArrayDocs.get(i);
			if ( "GRAPH".equals(node.get("type").getTextValue()) == false ) continue;
			
			ArrayNode jsonArrayDoc = (ArrayNode)node.get("items");
			
			/*int id = -1;
			JsonNode idNode = (JsonNode)node.get("id");
			if (idNode != null) if (idNode.isTextual()) id = idNode.getIntValue();*/
			
			
			//DocGraph docGraph = new DocGraph(id);
			XobjectEx xobj = dbex.createObject(-1);
			//docGraph.name = new String (node.get("name").getTextValue());
			xobj.attrAdd(new XattrTPE("graph"));
			xobj.attrAdd(new XattrSTR("name", node.get("name").getTextValue()));
			
			//dbex.getDocs().add(docGraph);
			
			XattrGRP attrGrp = new XattrGRP(-1, xobj);
			xobj.attrAdd(attrGrp);
			
			for ( int ii = 0; ii < jsonArrayDoc.size(); ii++ )
			{	ObjectNode item = (ObjectNode)jsonArrayDoc.get(ii);
			
				String type = "object";
				JsonNode typeNode = (JsonNode)item.get("type");
				if (typeNode != null) if (typeNode.isTextual()) type = typeNode.getTextValue();
				
				if (type.equals("graph")) continue;
				
				//GraphItem gitem = null;
				
				
				Point2D.Double xy = new Point2D.Double(
						item.get("x").getValueAsDouble(),
						item.get("y").getValueAsDouble());

				
				/*if (type.equals("graph")) {
					gitem = new GraphItemGraph(item.get("id").getValueAsInt(), xy); 
				}
				else {
					XobjectEx obj = (XobjectEx)(dbex.getById(item.get("id").getValueAsInt()));
					if (obj == null ) continue;
					gitem = new GraphItemXobject(obj, xy);
				}
				
				if (gitem == null) continue;
				
				docGraph.add(gitem);*/
				//gitem.doc = docGraph;
				
				int id = item.get("id").getValueAsInt();
				
				Xobject obji = dbex.getById(id);
				XattrGXY attrGXY = new XattrGXY(-1, attrGrp.getId(), "", obji, xy);
				obji.attrAdd(attrGXY);
				
				attrGrp.add(attrGXY.getId(), "");
			}
		}		
	}
	
	private void loadEstimates() {
		ArrayNode jsonArrayEstimates = (ArrayNode)jsonRoot.get("estimates");
		
		if (jsonArrayEstimates != null) for ( int i = 0; i < jsonArrayEstimates.size(); i++ )
		{	ObjectNode node = (ObjectNode)jsonArrayEstimates.get(i);
			LinkEstimate estimate = new LinkEstimate( 	node.get("objectType1").getValueAsText(),
														node.get("linkName1").getValueAsText(),
														node.get("objectType2").getValueAsText(),
														node.get("linkName2").getValueAsText() );
			XdbEx dbex = (XdbEx)xdb;
			dbex.metadata.estimates.add(estimate);
		}
		
	}
	
	private void loadTypes() {
		ArrayNode jsonArrayTypes = (ArrayNode)jsonRoot.get("types");
		
		if (jsonArrayTypes != null )for ( int i = 0; i < jsonArrayTypes.size(); i++ )
		{	ObjectNode nodeType = (ObjectNode)jsonArrayTypes.get(i);
			Type type = new Type(nodeType.get("id").getValueAsText());
			 
			xdbEx().metadata.types.put(type.id, type);
			
			ArrayNode jsonAttrDefs = (ArrayNode)nodeType.get("attrDefs");
			for (int adi = 0; adi < jsonAttrDefs.size(); adi++) {
				ObjectNode nodeAttrdef = (ObjectNode)jsonAttrDefs.get(adi);
				String adType = nodeAttrdef.get("type").getValueAsText();
				
				if ("TPE".equals(adType)) {
					type.attrdefs.add(new Attrdef(Xattr.Type.TPE, nodeAttrdef.get("name").getValueAsText(), 1, 1, ""));
				}
				else if ("STR".equals(adType)) {
					type.attrdefs.add(new Attrdef(Xattr.Type.STR, 
							nodeAttrdef.get("name").getValueAsText(), 
							nodeAttrdef.get("minCount").getValueAsInt(),
							nodeAttrdef.get("maxCount").getValueAsInt(),
							nodeAttrdef.get("value").getValueAsText() ) );
				}
				else if ("URL".equals(adType)) {
					type.attrdefs.add(new Attrdef(Xattr.Type.URL, 
							nodeAttrdef.get("name").getValueAsText(), 
							nodeAttrdef.get("minCount").getValueAsInt(),
							nodeAttrdef.get("maxCount").getValueAsInt(),
							nodeAttrdef.get("value").getValueAsText() ) );
				}
				else if ("GRP".equals(adType)) {
					type.attrdefs.add(new Attrdef(Xattr.Type.GRP, nodeAttrdef.get("name").getValueAsText(), 1, 1, ""));
				}
			}
			
			ArrayNode jsonDescrs = (ArrayNode)nodeType.get("descrs");
			for (int di = 0; di < jsonDescrs.size(); di++) {
				ObjectNode nodeDescr = (ObjectNode)jsonDescrs.get(di);
				
				Descr descr = new Descr();
				type.descrs.add(descr);
				
				ArrayNode jsonDescrItems = (ArrayNode)nodeDescr.get("items");

				for (int ii = 0; ii < jsonDescrItems.size(); ii++) {
					ObjectNode nodeDescrItem = (ObjectNode)jsonDescrItems.get(ii);

					String descrType = nodeDescrItem.get("type").getValueAsText();
				
					if ("VALUE".equals(descrType)) {
						descr.items.add(new DescrItemValue(nodeDescrItem.get("value").getValueAsText()));
					}
					if ("PATH".equals(descrType)) {
						DescrItemPath itemPath = new DescrItemPath();
						descr.items.add(itemPath);
						
						ArrayNode jsonPath = (ArrayNode)nodeDescrItem.get("path");
						
						for (int p = 0; p < jsonPath.size(); p++) {
							ObjectNode jsonPathItem = (ObjectNode)jsonPath.get(p);
							
							itemPath.path.add(jsonPathItem.get("value").getValueAsText());
						}
					}
				}
			}
		}
	}
	
	private void loadStyles() {
		ArrayNode jsonArrayStyles = (ArrayNode)jsonRoot.get("legend");
		
		if (jsonArrayStyles != null) for ( int i = 0; i < jsonArrayStyles.size(); i++ ) {
			ObjectNode nodeStyle = (ObjectNode)jsonArrayStyles.get(i);
			Style style = new Style(nodeStyle.get("id").getValueAsText());
			xdbEx().metadata.legend.styles.put(style.id, style);
			
			ArrayNode jsonSfeats = (ArrayNode)nodeStyle.get("sfeats");
			for (int sfi = 0; sfi < jsonSfeats.size(); sfi++) {
				ObjectNode nodeSf = (ObjectNode)jsonSfeats.get(sfi);
				
				String type = nodeSf.get("type").getValueAsText();
				
				if ("SYMBOL".equals(type) ) {
					String symbolId = nodeSf.get("symbol").getValueAsText();
					Symbol symbol = xdbEx().metadata.legend.symbols.get(symbolId);
					style.sfeats.add(new SfeatSymbol(symbol));
				}
				else {
					Color color = new Color( nodeSf.get("red").getValueAsInt(),
							                 nodeSf.get("green").getValueAsInt(),
							                 nodeSf.get("blue").getValueAsInt() );
					double offset = nodeSf.get("offset").getValueAsDouble();
					
					if ("LINE".equals(type) ) {
						SfeatLine sfLine = new SfeatLine(color, offset);
						style.sfeats.add(sfLine);
						
						TextNode symbolBeginNode = (TextNode)nodeSf.get("symbol_begin");
						if (symbolBeginNode != null) {
							Symbol symbol = xdbEx().metadata.legend.symbols.get(symbolBeginNode.getValueAsText());
							sfLine.symbolBegin = symbol;
						}
						TextNode symbolEndNode = (TextNode)nodeSf.get("symbol_end");
						if (symbolEndNode != null) {
							Symbol symbol = xdbEx().metadata.legend.symbols.get(symbolEndNode.getValueAsText());
							sfLine.symbolEnd = symbol;
						}
					}
					else if ("AREA".equals(type) ) {
						SfeatArea sfArea = new SfeatArea(color, offset);
						style.sfeats.add(sfArea);
					}
				}
			}
			
			//style.symbol = xdb.metadata.legend.symbols.get(style.id);
			Math.abs(0);
		}
	}
	
	private void loadSymbols() {
		ArrayNode jsonArraySymbols = (ArrayNode)jsonRoot.get("symbols");
		if (jsonArraySymbols == null) return; 
		
		for ( int i = 0; i < jsonArraySymbols.size(); i++ ) {
			ObjectNode nodeSymbol = (ObjectNode)jsonArraySymbols.get(i);
			Symbol symbol = new Symbol(nodeSymbol.get("id").getValueAsText());
			xdbEx().metadata.legend.symbols.put(symbol.id, symbol);
			
			ArrayNode jsonSitems = (ArrayNode)nodeSymbol.get("items");
			for (int si = 0; si < jsonSitems.size(); si++) {
				ObjectNode jsonSitem = (ObjectNode)jsonSitems.get(si);
				String subtype = jsonSitem.get("subtype").getValueAsText();
				SymbolItemIregular.Type type = SymbolItemIregular.Type.LINE;
				if ("area".equals(subtype)) type = SymbolItemIregular.Type.AREA;
				if ("line_closed".equals(subtype)) type = SymbolItemIregular.Type.LINE_CLOSED;
				Color color = new Color( jsonSitem.get("red").getValueAsInt(),
						           jsonSitem.get("green").getValueAsInt(),
						           jsonSitem.get("blue").getValueAsInt() );
				SymbolItemIregular item = new SymbolItemIregular(type, color);
				
				symbol.items.add(item);
				
				ArrayNode jsonArrayPoints = (ArrayNode)jsonSitem.get("points");
				for (int pi = 0; pi < jsonArrayPoints.size(); pi++) {
					ObjectNode jsonpoint = (ObjectNode)jsonArrayPoints.get(pi);
					item.points.add(Symbol.createPoint( jsonpoint.get("x").getValueAsDouble(),
							                            jsonpoint.get("y").getValueAsDouble() ));
				}
			}
		}
	}
}
